#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

// 假设的TLV消息结构，需要与服务器保持一致
typedef struct {
    int type;
    int value_len;
    char value[1024];
} TLVMsg;

// 发送消息函数（需要与服务器端的定义一致）
int sendmasge(int netfd, int cont, int len, char *buf)
{
    TLVMsg sendmsg;
    memset(&sendmsg, 0, sizeof(TLVMsg));
    
    sendmsg.type = 8;
    sendmsg.value_len = len;
    if (len > 0 && buf != NULL) {
        memcpy(sendmsg.value, buf, len);
    }
    
    // 发送类型
    if (send(netfd, &sendmsg.type, sizeof(int), 0) != sizeof(int)) {
        perror("send type failed");
        return -1;
    }
    
    // 发送长度
    if (send(netfd, &sendmsg.value_len, sizeof(int), 0) != sizeof(int)) {
        perror("send value_len failed");
        return -1;
    }
    
    // 发送值
    if (len > 0 && send(netfd, sendmsg.value, len, 0) != len) {
        perror("send value failed");
        return -1;
    }
    
    return 0;
}

// 接收消息函数（需要与服务器端的定义一致）
int recvmasge(int netfd, TLVMsg *msg)
{
    memset(msg, 0, sizeof(TLVMsg));
    
    // 接收类型
    if (recv(netfd, &msg->type, sizeof(int), MSG_WAITALL) != sizeof(int)) {
        perror("recv type failed");
        return -1;
    }
    
    // 接收长度
    if (recv(netfd, &msg->value_len, sizeof(int), MSG_WAITALL) != sizeof(int)) {
        perror("recv value_len failed");
        return -1;
    }
    
    // 检查长度是否合理
    if (msg->value_len < 0 || msg->value_len >= sizeof(msg->value)) {
        printf("Invalid value length: %d\n", msg->value_len);
        return -1;
    }
    
    // 接收值
    if (recv(netfd, msg->value, msg->value_len, MSG_WAITALL) != msg->value_len) {
        perror("recv value failed");
        return -1;
    }
    
    // 确保字符串结束
    msg->value[msg->value_len] = '\0';
    printf("收到消息：type=%d, value_len=%d, value=%s\n", 
           msg->type, msg->value_len, msg->value);
    
    return 0;
}

int main()
{
    // 创建socket
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 设置服务器地址
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(36666);
    
    // 转换IP地址
    if (inet_pton(AF_INET, "192.168.7.22", &serv_addr.sin_addr) <= 0) {
        perror("invalid address");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    // 连接服务器
    if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        perror("connection failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }
    
    printf("客户端连接到服务器成功, sockfd=%d\n", sockfd);
    
    // 定义消息类型（需要与服务器保持一致）
    // 假设这些是您的命令类型
    #define CMD_LOGIN 8
    #define CMD_QUIT 12
    
    char username[100];
    char password[100];
    TLVMsg response;
    
    while(1)
    {
        // 获取用户名和密码
        printf("请输入用户名: ");
        if (fgets(username, sizeof(username), stdin) == NULL) {
            break;
        }
        // 去除换行符
        username[strcspn(username, "\n")] = 0;
        
        printf("请输入密码: ");
        if (fgets(password, sizeof(password), stdin) == NULL) {
            break;
        }
        // 去除换行符
        password[strcspn(password, "\n")] = 0;
        
        // 发送登录信息
        // 假设CMD_LOGIN是登录命令类型
        if (sendmasge(sockfd, CMD_LOGIN, strlen(username), username) != 0) {
            printf("发送用户名失败\n");
            break;
        }
        
        // 发送密码
        if (sendmasge(sockfd, CMD_LOGIN + 1, strlen(password), password) != 0) {
            printf("发送密码失败\n");
            break;
        }
        
        // 接收服务器响应
        if (recvmasge(sockfd, &response) == 0) {
            printf("服务器响应: %s\n", response.value);
            
            // 如果登录成功，可以进入命令循环
            if (response.type == CMD_LOGIN && strcmp(response.value, "登录成功") == 0) {
                printf("登录成功，可以开始发送命令\n");
                break; // 跳出登录循环，进入命令循环
            }
        } else {
            printf("接收响应失败\n");
            break;
        }
    }
    
    // 命令循环
    char command[100];
    while(1)
    {
        printf("请输入命令 (输入quit退出): ");
        if (fgets(command, sizeof(command), stdin) == NULL) {
            break;
        }
        
        // 去除换行符
        command[strcspn(command, "\n")] = 0;
        
        // 检查是否退出
        if (strcmp(command, "quit") == 0) {
            // 发送退出命令
            sendmasge(sockfd, CMD_QUIT, 0, NULL);
            break;
        }
        
        // 这里需要根据命令解析出命令类型和参数
        // 简化处理：假设所有命令都是LS命令
        if (sendmasge(sockfd, 2, strlen(command), command) != 0) {
            printf("发送命令失败\n");
            break;
        }
        
        // 接收响应
        if (recvmasge(sockfd, &response) != 0) {
            printf("接收响应失败\n");
            break;
        }
        
        printf("命令执行结果: %s\n", response.value);
    }
    
    close(sockfd);
    printf("连接已关闭\n");
    return 0;
}